package nc.impl.hrpbm.deptbuget;

import nc.bs.dao.BaseDAO;
import nc.bs.hrpbm.deptbudget.DeptBudgetRevenueDetailService;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.pub.hrpbm.util.HrpbmReportUtils;
import nc.pub.smart.context.SmartContext;
import nc.pub.smart.data.DataSet;
import nc.pub.smart.metadata.Field;
import nc.pub.smart.metadata.MetaData;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nccloud.commons.lang.ArrayUtils;
import org.apache.commons.collections4.CollectionUtils;
import uap.lfw.bq.portal.base.StringUtils;

import java.math.BigDecimal;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/*
* 收入明细表
* 这张表可谓年度top1的感人级别
* 数据少 一下能计算完 看的也清晰 取数也方便 真的泪目了
* 语义模型-预置
* 自由报表-全局
* */

public class DeptBudgetRevenueDetailServiceImpl implements DeptBudgetRevenueDetailService{
	HrpbmReportUtils Utils = new HrpbmReportUtils();
	private BaseDAO baseDAO;

	public BaseDAO getBaseDAO() {
		return baseDAO == null ? new BaseDAO() : baseDAO;
	}

	public static final String cwbudgetdeptcode = "405"; // 财务部门编码
	public static final String firstparentcode = "1"; // 收支项目: 收入科目编码

	String[] fields = new String[] { "inoutbusiclassname","deptname","nyear","type_name" ,"amount_firstdown","inoutbusiclasscode","fundsourceamount","yeartypename"};
	String[] fieldCaptions = new String[] {"收支科目", "部门名称","年度", "项目分类","合计" ,"科目编码","来源合计","收入类型"};
	
	
	@Override
	public DataSet process(SmartContext context) throws BusinessException {
		// TODO Auto-generated method stub
		MetaData metadata = this.initMetaData();
		Utils.handelContext(context);
		List<Map<String, Object>>  sqlResult=queryBudgetMakeData(context);
		
		return buildDataSetobj(metadata, sqlResult, fields);
	}

	
	
	public List<Map<String, Object>> queryBudgetMakeData(SmartContext context)
			throws BusinessException {
		String pk_org = (String) context.getAttribute("pk_org");
		String budgetdept = (String) context.getAttribute("pk_budgetdept");
		String pk_inoutclass = (String) context.getAttribute("pk_inoutclass");
		String nyear = (String) context.getAttribute("nyear") == null ? "2025":(String) context.getAttribute("nyear");
		String isfund = (String) context.getAttribute("isfund");

		String inoutlevel = (String) context.getAttribute("level");
		String f1project =  (String)context.getAttribute("f1project");
		String f2project = (String) context.getAttribute("f2project");
	//	String f3project = (String) context.getAttribute("f3project");

		StringBuffer sql = new StringBuffer();
		sql.append("SELECT hbd.pk_budgetdept as pk_budgetdept,");//
		sql.append("       '本年收入' as yeartypename,");//
		sql.append("       hbd.name as deptname,");//
		sql.append("       hbd.code as deptcode,");//
		sql.append("       hbrd.nyear AS nyear,");//
		sql.append("       ee.code as inoutbusiclasscode,");//
		sql.append("       ee.name as inoutbusiclassname,");//
		sql.append("       ee.pk_inoutbusiclass as pk_inoutclass,");//
		sql.append("       ee.pk_parent         as inoutbusiclassparent,");//
		sql.append("       fip_docview_b.sfzjcode AS sfzjcode,");//
		sql.append("       projectclass.eps_name AS type_name,");//
		sql.append("       CASE");//
		sql.append("         WHEN hbr.approvestatus = '1' THEN");//
		sql.append("          nvl(hbrd.amount_firstdown, 0)");//
		sql.append("         ELSE");//
		sql.append("          nvl(hbrd.amount_firstup, 0)");//
		sql.append("       END AS amount_firstdown");//
		sql.append("  FROM hrpbm_budgetreply hbr");//
		sql.append("  LEFT JOIN hrpbm_budgetreplydetail hbrd");//
		sql.append("    ON hbrd.pk_budgetreply = hbr.pk_budgetreply");//
		sql.append("  LEFT JOIN hrpbm_budgetdept hbd");//
		sql.append("    ON hbd.pk_budgetdept = hbrd.pk_budgetdept");//
		sql.append("  LEFT JOIN bd_inoutbusiclass ee");//
		sql.append("    ON ee.pk_inoutbusiclass = hbrd.pk_inoutclass");//
		sql.append("  LEFT JOIN bd_project project");//
		sql.append("    ON project.pk_project = hbrd.pk_project");//
		sql.append("  LEFT JOIN pm_eps projectclass");//
		sql.append("    ON projectclass.pk_eps = project.pk_eps");//
		sql.append("  LEFT JOIN (SELECT DISTINCT kmdzb.factorvalue5 AS pk_inoutbusiclass,");//
		sql.append("                             szxm.code          AS szxmcode,");//
		sql.append("                             szxm.name          AS szxmname,");//
		sql.append("                             sfzj.code          AS sfzjcode,");//
		sql.append("                             sfzj.NAME          AS sfzjname");//
		sql.append("               FROM fip_docview_b kmdzb");//
		sql.append("               LEFT JOIN fip_docview kmdz");//
		sql.append("                 ON kmdz.pk_classview = kmdzb.pk_classview");//
		sql.append("               LEFT JOIN bd_inoutbusiclass szxm");//
		sql.append("                 ON kmdzb.factorvalue5 = szxm.pk_inoutbusiclass");//
		sql.append("               LEFT JOIN bd_defdoc bmjjfl");//
		sql.append("                 ON kmdzb.factorvalue1 = bmjjfl.pk_defdoc");//
		sql.append("               LEFT JOIN bd_defdoc sfzj");//
		sql.append("                 ON kmdzb.factorvalue3 = sfzj.pk_defdoc");//
		sql.append("               LEFT JOIN bd_defdoc kmlx");//
		sql.append("                 ON kmdzb.factorvalue6 = kmlx.pk_defdoc");//
		sql.append("               LEFT JOIN bd_accasoa bd_accasoa");//
		sql.append("                 ON kmdzb.desdocvalue = bd_accasoa.pk_accasoa");//
		sql.append("               LEFT JOIN bd_account bd_account");//
		sql.append("                 ON bd_accasoa.pk_account = bd_account.pk_account");//
		sql.append("              WHERE kmdz.VIEWCODE = 'YS001') fip_docview_b");//
		sql.append("    ON hbrd.pk_inoutclass = fip_docview_b.pk_inoutbusiclass");//
		sql.append(" WHERE hbrd.pk_budgettype = 'YS01'");//
		sql.append("   AND hbrd.nyear = '"+nyear+"' ");

		if(StringUtils.isNotBlank(isfund)) {
			sql.append( "   AND fip_docview_b.sfzjcode = '"+isfund+"'");
		}

		if (StringUtils.isNotBlank(pk_inoutclass)) {
			String pk_inoutclassInString = convertToInClause(pk_inoutclass);
			sql.append("   AND hbrd.pk_inoutclass in (" + pk_inoutclassInString + ") \n");
		}

		if (StringUtils.isNotBlank(pk_org) && !"GLOBLE00000000000000".equals(pk_org)) {
			sql.append("   AND hbrd.pk_org = '" + pk_org + "' \n");// 财务组织
		}

		if (StringUtils.isNotBlank(budgetdept)) {
			String pk_budgetdeptInString = convertToInClause(budgetdept);
			sql.append("   AND hbrd.pk_budgetdept  in (" + pk_budgetdeptInString + ") \n");// 预算科室
		}

		sql.append(" ORDER BY inoutbusiclasscode;");

		List<Map<String,Object>> list = (ArrayList<Map<String,Object>>)getBaseDAO().executeQuery(sql.toString(), new MapListProcessor());
		//initFundsource(list);
		List<Map<String,Object>> newList = new ArrayList();

		initInoutclasscode(list);

		return list;
	}

	private Field[] initField() {
		Field[] FieldInfo = new Field[fields.length];
		for (int i = 0; i < fields.length; i++) {
			Field filed = new Field();
			filed.setCaption(fieldCaptions[i]);
			filed.setDbColumnType(Types.VARCHAR);
			if (i == 4 || i == 6) { // 5,7对应编制金额，批复金额，金额是否需要调整字段类型，根据情况定
				filed.setDbColumnType(Types.DECIMAL);
				filed.setPrecision(28);
				filed.setScale(2);
			}
			
			filed.setFldname(fields[i]);
//			if (i == 4 || i == 6 ) {// 视情况而定
//				filed.setPrecision(500);
//				filed.setDbColumnType(Types.VARCHAR);
//			}
			FieldInfo[i] = filed;
		}
		return FieldInfo;
	}
	/**
	 * 	初始化metadata
	 * @return
	 */
	private MetaData initMetaData() {
		Field[] FieldInfo = initField();
		MetaData md = new MetaData();
		for (int i = 0; i < fields.length; i++) {
			md.addField(FieldInfo[i]);
		}
		return md;
	}


	public static DataSet buildDataSetobj(MetaData meta, List<Map<String, Object>> list, String[] fields) {
		if (ArrayUtils.isEmpty(fields)) {
			ExceptionUtils.wrappBusinessException("报表字段列不能为空，请检查！！！");
		}
		DataSet ds = null;
		if (null == list || list.size() == 0) {
			// 返回空数据集, 用于给语义模型加载空数据用
			Object[][] datas = new Object[1][fields.length];
			ds = new DataSet(meta, datas);
		} else {
			Object[][] datas = new Object[list.size()][fields.length];
			for(int i = 0;i < list.size();i++){
				for(int j = 0; j < fields.length; j++ ) {
					datas[i][j] = list.get(i).get(fields[j].toString());
							//vos[i].getAttributeValue(fields[j]);
				}
			}
			ds = new DataSet(meta, datas);
		}
		return ds;
	}

	public List<Map<String, Object>> initInoutclasscode(List<Map<String, Object>> list) {

		if(CollectionUtils.isEmpty(list)){
			return new ArrayList<>();
		}

		Map<String,List<Map<String, Object>>> groupMap = new HashMap<>();
		for (int i = 0; i < list.size(); i++) {

			Map<String, Object> map = list.get(i);

			/**
			 * 聚类数据分组
			 */
			String inoutclasscode = (String) map.get("inoutbusiclassname");
			String deptcode = (String) map.get("deptcode");
			String key = inoutclasscode + "-" + deptcode;

			List<Map<String, Object>> mapList = null;
			if(groupMap.containsKey(key)){
				mapList = groupMap.get(key);
			}else{
				mapList = new ArrayList<>();
			}
			mapList.add(map);
			groupMap.put(key, mapList);
		}

		List<Map<String, Object>> returnList = new ArrayList<>();

		for (Entry<String, List<Map<String, Object>>> entry : groupMap.entrySet()) {
			List<Map<String, Object>> value = entry.getValue();

			BigDecimal fundsourceamount = new BigDecimal(0);

			Map<String, Object> baseMap = new HashMap<>();

			for (int i = 0; i < value.size(); i++) {
				Map<String, Object> map = value.get(i);
				BigDecimal amount = new BigDecimal(0);

				/**
				 * 封装来源款项
				 */
				if(map.get("amount_firstdown") instanceof BigDecimal){
					amount = (BigDecimal) map.get("amount_firstdown");
				}else{
					Integer amountInt = (Integer) map.get("amount_firstdown");
					amount = new BigDecimal(amountInt);
				}

				fundsourceamount = fundsourceamount.add(amount);

				if(i==0){
					baseMap = map;
				}
			}

			baseMap.put("fundsourceamount", fundsourceamount);

			returnList.add(baseMap);
		}

		return returnList;
	}
	
	public static String convertToInClause(String value) {  
		if(StringUtils.isBlank(value)) {
			return ""; 
		}
		String[] values = value.split(",");
          
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < values.length; i++) {  
            sb.append('\'').append(values[i]).append('\'');   
            if (i < values.length - 1) {  
                sb.append(',');  
            }  
        }  
        return sb.toString();
    }

}
